package com.ahwei.gateway.config;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.cloud.nacos.NacosConfigManager;
import com.alibaba.cloud.nacos.NacosConfigProperties;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionRepository;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;

/**
 * <p>
 * 这是一个Java文件！
 * </p>
 *
 * @author ahWei
 * @email：ahwei163@qq.com
 * @since 2022-06-08 18:59:47
 */
@Slf4j
@Component
public class NacosRouteDefinitionRepository implements RouteDefinitionRepository {
    // nacos配置参数
    private NacosConfigProperties nacosConfigProperties;
    // 更新路由信息时需要的事件发布类
    private ApplicationEventPublisher publisher;

    // 构造器
    public NacosRouteDefinitionRepository(ApplicationEventPublisher publisher, NacosConfigProperties nacosConfigProperties) {
        this.publisher = publisher;
        this.nacosConfigProperties = nacosConfigProperties;
        // 启动时注册Nacos监听器
        addListener();
    }

    /**
     * 添加Nacos监听
     */
    private void addListener() {
        try {
            new NacosConfigManager(nacosConfigProperties).getConfigService()
                    .addListener(NacosGatewayConfig.NACOS_DATA_ID, NacosGatewayConfig.NACOS_GROUP_ID, new Listener() {
                        @Override
                        public Executor getExecutor() {
                            return null;
                        }

                        // Nacos中有变化时的响应方法
                        @Override
                        public void receiveConfigInfo(String configInfo) {
                            // Nacos中路由数据变化后，只要ApplicationEventPublisher推送一个RefreshRoutesEvent事件即可，
                            // gateway会自动监听该事件并调用getRouteDefinitions方法更新路由信息
                            publisher.publishEvent(new RefreshRoutesEvent(this));
                        }
                    });
        } catch (NacosException e) {
            log.error("nacos-addListener-error", e);
        }
    }

    // Gateway调用getRouteDefinitions方法来读取路由信息
    @Override
    public Flux<RouteDefinition> getRouteDefinitions() {
        try {
            // 使用指定data-id和group访问Nacos配置中的内容
            String content = new NacosConfigManager(nacosConfigProperties)
                    .getConfigService()
                    .getConfig(NacosGatewayConfig.NACOS_DATA_ID, NacosGatewayConfig.NACOS_GROUP_ID,5000);
            System.out.println("content: " + content);
            // 解析JSON数据来构建路由对象
            List<RouteDefinition> routeDefinitions = getListByStr(content);
            // 将路由数据添加到Gateway中
            return Flux.fromIterable(routeDefinitions);
        } catch (NacosException e) {
            log.error("getRouteDefinitions by nacos error", e);
        }

        return Flux.fromIterable(CollUtil.newArrayList());
    }

    // 解析路由配置信息 ―― 配置文件的格式一定要写对！
    private List<RouteDefinition> getListByStr(String content) {
        if (StrUtil.isNotEmpty(content)) {
            return cn.hutool.json.JSONUtil.toList(content, RouteDefinition.class);
        }
        return new ArrayList<>(0);
    }

    @Override
    public Mono<Void> save(Mono<RouteDefinition> route) {
        return null;
    }

    @Override
    public Mono<Void> delete(Mono<String> routeId) {
        return null;
    }
}
